#include "HY1C_out.h"
/* -------------------------------------------------------------------------- */
/* Module get_l2prod_index - maintains a list of all possible L2 products and */
/* returns attributes on request.                                             */
/*                                                                            */
/* B. A. Franz, SAIC GSC, NASA/SIMBIOS Project, April 1999                    */
/* -------------------------------------------------------------------------- */

#include <stdio.h>
#include <strings.h>
#include "l12_proto.h"
#include "l2prod.h"

#define ARRAY_CHUNK_SIZE 20

static l2prodstr **l2prod_array = NULL; // array of pointers to all the products
static int l2prod_num = 0; // number of products in the array
static int l2prod_storage = 0; // size of the array holding the pointers

/* init a product structure */
void initProduct(l2prodstr* l2prod) {
    l2prod->param_type = PARAM_TYPE_NONE;
    l2prod->name_prefix[0] = '\0';
    l2prod->name_suffix[0] = '\0';
    l2prod->cat_ix = -1;
    l2prod->prod_ix = -1;
    l2prod->datatype = DFNT_FLOAT32;
    l2prod->slope = 1.0;
    l2prod->offset = 0.0;
    l2prod->min = 0;
    l2prod->max = 0;
    l2prod->rank = 2;
    strcpy(l2prod->title_format, "no title format yet (%d)");
    strcpy(l2prod->title, "no title yet");
    strcpy(l2prod->units, "undefined units");
    l2prod->badData = BAD_FLT;
    l2prod->product_id[0] = '\0';
    l2prod->algorithm_id[0] = '\0';
    l2prod->standard_name[0] = '\0';
}

/* create a new product structure, init it, add it to the global array
 * and return the pointer.
 */
l2prodstr* createNewProduct() {

    // allocate the structure
    l2prodstr* l2prod = (l2prodstr*) malloc(sizeof (l2prodstr));

    initProduct(l2prod);
    
    // add the product structure to the global array
    l2prod_num++;
    if (l2prod_num > l2prod_storage) {
        l2prod_storage += ARRAY_CHUNK_SIZE;
        l2prod_array = (l2prodstr**) realloc(l2prod_array, l2prod_storage * sizeof (l2prodstr*));
    }
    l2prod_array[l2prod_num - 1] = l2prod;

    return l2prod;
}

/* -------------------------------------------------------------------------- */
void init_l2prod(int32 numPixels, int32 numScans) {
    int i;
    l2prodstr *l2prod;

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_logchl;
    strncpy(l2prod->name_prefix, "logchl", UNITLEN);
    strncpy(l2prod->units, "log(mg m^-3)", UNITLEN);
    strncpy(l2prod->title, "log(e) of Chlorophyll Concentration", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_oc2;
    strncpy(l2prod->name_prefix, "chl_oc2", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oc2", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OC2 Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_oc3;
    strncpy(l2prod->name_prefix, "chl_oc3", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oc3", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OC3 Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_oc3c;
    strncpy(l2prod->name_prefix, "chl_oc3c", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oc3c", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OC3c Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_oc4;
    strncpy(l2prod->name_prefix, "chl_oc4", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oc4", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OC4 Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_hu;
    strncpy(l2prod->name_prefix, "chl_hu", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "hu", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, Hu Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_oci;
    strncpy(l2prod->name_prefix, "chl_oci", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oci", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OCI Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_cdomcorr_morel;
    strncpy(l2prod->name_prefix, "chl_cdomcorr_morel", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "cdom_corr", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, Default Algorithm with Morel CDOM correction", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Lt;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "Lt_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Calibrated TOA radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Lt_unc;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "Lt_unc_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in TOA radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_BT;
    l2prod->param_type = PARAM_TYPE_IR_WAVE;
    strncpy(l2prod->name_prefix, "BT_", UNITLEN);
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title_format, "Brightness temperature at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "brightness_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_nw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "nw_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00001;
    l2prod->offset = 1.2;
    l2prod->min = 1.3;
    l2prod->max = 1.4;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "T & S corrected seawater index of refraction at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aw_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "T & S corrected seawater absorption at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbw_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "T & S corrected backscatter at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_las;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, Loisel and Stramski algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_b_las;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "b_", UNITLEN);
    strncpy(l2prod->name_suffix, "_las", UNITLEN);
    strncpy(l2prod->product_id, "b", UNITLEN);
    strncpy(l2prod->algorithm_id, "las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total scatter at %3d nm, Loisel and Stramski algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_c_las;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "c_", UNITLEN);
    strncpy(l2prod->name_suffix, "_las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Beam attenuation at %3d nm, Loisel and Stramski algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_las;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, Loisel and Stramski algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_las;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particle backscatter at %3d nm, Loisel and Stramski algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbps_las;
    strncpy(l2prod->name_prefix, "bbp_s_las", UNITLEN);
    strncpy(l2prod->product_id, "bbp_s", UNITLEN);
    strncpy(l2prod->algorithm_id, "las", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    l2prod->min = 0.0;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "bbp spectral parameter from LAS model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_pml;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_pml", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, PML algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_pml;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_pml", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, PML algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_pml;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_pml", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particle backscatter at %3d nm, PML algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_pml;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_", UNITLEN);
    strncpy(l2prod->name_suffix, "_pml", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to phytoplankton at %3d nm, PML algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_pml;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_pml", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %3d nm, PML algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_b_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "b_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total scattering at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_c_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "c_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Beam attenuation at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particulate backscatter at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to phytoplankton at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_qaa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %3d nm, QAA algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_mod_rrs_qaa;
    strncpy(l2prod->name_prefix, "mod_rrs_qaa", UNITLEN);
    strncpy(l2prod->product_id, "mod_rss", UNITLEN);
    strncpy(l2prod->algorithm_id, "qaa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    l2prod->min = 0.000002;
    l2prod->max = 0.04;
    strncpy(l2prod->units, "sr-1", UNITLEN);
    strncpy(l2prod->title, "Modeled Rrs, Lee (2006)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_qaa;
    strncpy(l2prod->name_prefix, "flags_qaa", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "qaa", UNITLEN);
    l2prod->datatype = DFNT_UINT8;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags, QAA model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_carder;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_carder;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_carder;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particulate backscatter at %3d nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_carder;
    strncpy(l2prod->name_prefix, "aph_carder", UNITLEN);
    strncpy(l2prod->product_id, "aph", UNITLEN);
    strncpy(l2prod->algorithm_id, "carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to phytoplankton at 400 nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_carder;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_", UNITLEN);
    strncpy(l2prod->name_suffix, "_carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to phytoplankton at %3d nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_carder;
    strncpy(l2prod->name_prefix, "adg_carder", UNITLEN);
    strncpy(l2prod->product_id, "adg", UNITLEN);
    strncpy(l2prod->algorithm_id, "carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to gelbstof and detrital material at 675 nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_carder;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %3d nm, Carder algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_carder;
    strncpy(l2prod->name_prefix, "chl_carder", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "carder", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, Carder model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_carder_emp;
    strncpy(l2prod->name_prefix, "chl_carder_empirical", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "carder_emp", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, Carder empirical algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_carder;
    strncpy(l2prod->name_prefix, "flags_carder", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "carder", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags, Carder model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_giop;
    strncpy(l2prod->name_prefix, "chl_giop", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_unc_giop;
    strncpy(l2prod->name_prefix, "chl_unc_giop", UNITLEN);
    strncpy(l2prod->product_id, "chl_unc", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Uncertainty in Chlorophyll Concentration, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_rrsdiff_giop;
    strncpy(l2prod->name_prefix, "rrsdiff_giop", UNITLEN);
    strncpy(l2prod->product_id, "rrsdiff", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Fractional mean Rrs difference, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aphs_giop;
    strncpy(l2prod->name_prefix, "aph_s_giop", UNITLEN);
    strncpy(l2prod->product_id, "aph_s", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "aph spectral parameter for GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adgs_giop;
    strncpy(l2prod->name_prefix, "adg_s_giop", UNITLEN);
    strncpy(l2prod->product_id, "adg_s", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "adg spectral parameter for GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbps_giop;
    strncpy(l2prod->name_prefix, "bbp_s_giop", UNITLEN);
    strncpy(l2prod->product_id, "bbp_s", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "bbp spectral parameter for GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chisqr_giop;
    strncpy(l2prod->name_prefix, "chisqr_giop", UNITLEN);
    strncpy(l2prod->product_id, "chisqr", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Chi-square per degree of freedom, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_iter_giop;
    strncpy(l2prod->name_prefix, "iter_giop", UNITLEN);
    strncpy(l2prod->product_id, "iter", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Iteration count, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_giop;
    strncpy(l2prod->name_prefix, "flags_giop", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags for GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_mRrs_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "mRrs_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Modeled remote sensing reflectance at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %3d nm, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particulate backscatter at %3d nm, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to phytoplankton at %3d nm, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, GIOP model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_unc_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_unc_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in absorption due to gelbstof and detrital material at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_unc_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_unc_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in particulate backscatter at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_unc_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_unc_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in absorption due to phytoplankton at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_unc_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_unc_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in total absorption at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_unc_giop;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_unc_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in total backscatter at %3d nm, GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fitpar_giop;
    l2prod->param_type = PARAM_TYPE_BAND;
    strncpy(l2prod->name_prefix, "fit_par_", UNITLEN);
    strncpy(l2prod->name_suffix, "_giop", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title_format, "Fitted parameter %d of GIOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_gsm;
    strncpy(l2prod->name_prefix, "chl_gsm", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, GSM model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_gsm;
    strncpy(l2prod->name_prefix, "chl_gsm01", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, GSM model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_iter_gsm;
    strncpy(l2prod->name_prefix, "iter_gsm", UNITLEN);
    strncpy(l2prod->product_id, "iter", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Iteration count, GSM model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_iter_gsm;
    strncpy(l2prod->name_prefix, "iter_gsm01", UNITLEN);
    strncpy(l2prod->product_id, "iter", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Iteration count, GSM model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_gsm;
    strncpy(l2prod->name_prefix, "adg_gsm", UNITLEN);
    strncpy(l2prod->product_id, "adg", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to gelbstof and detrital material at 443 nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_gsm;
    strncpy(l2prod->name_prefix, "adg_gsm01", UNITLEN);
    strncpy(l2prod->product_id, "adg", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to gelbstof and detrital material at 443 nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_gsm;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %d nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_gsm;
    strncpy(l2prod->name_prefix, "bbp_gsm", UNITLEN);
    strncpy(l2prod->product_id, "bbp", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Particulate backscatter at 443 nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_gsm;
    strncpy(l2prod->name_prefix, "bbp_gsm01", UNITLEN);
    strncpy(l2prod->product_id, "bbp", UNITLEN);
    strncpy(l2prod->algorithm_id, "gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Particulate backscatter at 443 nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_gsm;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bbp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Particulate backscatter at %3d nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aph_gsm;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aph_", UNITLEN);
    strncpy(l2prod->name_suffix, "_gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to phytoplankton at %3d nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_phytoplankton", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_gsm;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption at %3d nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_gsm;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_gsm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter at %3d nm, GSM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_a_niwa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "a_", UNITLEN);
    strncpy(l2prod->name_suffix, "_niwa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total absorption - water at %3d nm, NIWA / UoP / Moore algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bb_niwa;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "bb_", UNITLEN);
    strncpy(l2prod->name_suffix, "_niwa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Total backscatter - water at %3d nm, NIWA / UoP / Moore algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_niwa;
    strncpy(l2prod->name_prefix, "flags_niwa", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "niwa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags for NIWA/UoP/Moore IOP model", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_soa;
    strncpy(l2prod->name_prefix, "chl_soa", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, SOA model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_soa;
    strncpy(l2prod->name_prefix, "bbp_soa", UNITLEN);
    strncpy(l2prod->product_id, "bbp", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Particulate backscatter at 443nm, SOA model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_soa;
    strncpy(l2prod->name_prefix, "adg_soa", UNITLEN);
    strncpy(l2prod->product_id, "adg", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to gelbstof and detrital material at 443nm, SOA model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_pcentcdm_soa;
    strncpy(l2prod->name_prefix, "pcentcdm_soa", UNITLEN);
    strncpy(l2prod->product_id, "pcentcdm", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Ratio of acdm to atot", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_w0_soa;
    strncpy(l2prod->name_prefix, "w0_soa", UNITLEN);
    strncpy(l2prod->product_id, "w0", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Single-Scattering Albedo, 865nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_v_soa;
    strncpy(l2prod->name_prefix, "v_soa", UNITLEN);
    strncpy(l2prod->product_id, "v", UNITLEN);
    strncpy(l2prod->algorithm_id, "soa", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Junge Power Law V parameter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_sma;
    strncpy(l2prod->name_prefix, "chl_sma", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "sma", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, G88/Oc4v4 model", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bbp_sma;
    strncpy(l2prod->name_prefix, "bbp_sma", UNITLEN);
    strncpy(l2prod->product_id, "bbp", UNITLEN);
    strncpy(l2prod->algorithm_id, "sma", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000005;
    l2prod->offset = 0.14;
    l2prod->min = 0.000005;
    l2prod->max = 1.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Particulate backscatter at 443nm, SMA model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_backwards_scattering_coefficient_of_radiative_flux_in_sea_water_due_to_particles", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_sma;
    strncpy(l2prod->name_prefix, "adg_sma", UNITLEN);
    strncpy(l2prod->product_id, "adg", UNITLEN);
    strncpy(l2prod->algorithm_id, "sma", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    l2prod->min = 0.0001;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Absorption due to gelbstof and detrital material at 443nm, SMA model", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_w0_sma;
    strncpy(l2prod->name_prefix, "w0_sma", UNITLEN);
    strncpy(l2prod->product_id, "w0", UNITLEN);
    strncpy(l2prod->algorithm_id, "sma", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Single-Scattering Albedo, 865nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_dom_sma;
    strncpy(l2prod->name_prefix, "dom_sma", UNITLEN);
    strncpy(l2prod->product_id, "dom", UNITLEN);
    strncpy(l2prod->algorithm_id, "sma", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol model number", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_clark;
    strncpy(l2prod->name_prefix, "chl_clark", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "clark", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, D. Clark, 2003", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tsm_clark;
    strncpy(l2prod->name_prefix, "tsm_clark", UNITLEN);
    strncpy(l2prod->product_id, "tsm", UNITLEN);
    strncpy(l2prod->algorithm_id, "clark", UNITLEN);
    strncpy(l2prod->units, "mg l^-1", UNITLEN);
    strncpy(l2prod->title, "Total Suspended Matter, D. Clark, 2003", TITLELEN);
    strncpy(l2prod->standard_name, "mass_concentration_of_suspended_matter_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_poc_clark;
    strncpy(l2prod->name_prefix, "poc_clark", UNITLEN);
    strncpy(l2prod->product_id, "poc", UNITLEN);
    strncpy(l2prod->algorithm_id, "clark", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.2;
    l2prod->offset = 6400.0;
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Particulate Organic Carbon, D. Clark, 2003", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_organic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_poc_stramski_443;
    strncpy(l2prod->name_prefix, "poc", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.2;
    l2prod->offset = 6400.0;
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Particulate Organic Carbon, D. Stramski, 2007 (443/555 version)", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_organic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_poc_stramski_443;
    strncpy(l2prod->name_prefix, "poc_stramski", UNITLEN);
    strncpy(l2prod->product_id, "poc", UNITLEN);
    strncpy(l2prod->algorithm_id, "stramski", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.2;
    l2prod->offset = 6400.0;
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Particulate Organic Carbon, D. Stramski, 2007 (443/555 version)", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_organic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_poc_stramski_443;
    strncpy(l2prod->name_prefix, "poc_stramski_443", UNITLEN);
    strncpy(l2prod->product_id, "poc", UNITLEN);
    strncpy(l2prod->algorithm_id, "stramski", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.2;
    l2prod->offset = 6400.0;
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Particulate Organic Carbon, D. Stramski, 2007 (443/555 version)", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_organic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_poc_stramski_490;
    strncpy(l2prod->name_prefix, "poc_stramski_490", UNITLEN);
    strncpy(l2prod->product_id, "poc", UNITLEN);
    strncpy(l2prod->algorithm_id, "stramski_490", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.2;
    l2prod->offset = 6400.0;
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Particulate Organic Carbon, D. Stramski, 2007 (490/555 version)", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_organic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_l2_flags;
    strncpy(l2prod->name_prefix, "l2_flags", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Level-2 Processing Flags", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_num_iter;
    strncpy(l2prod->name_prefix, "num_iter", UNITLEN);
    strncpy(l2prod->product_id, "aer_num_iter", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Number of Aerosol Iterations", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_num_iter;
    strncpy(l2prod->name_prefix, "aer_num_iter", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Number of Aerosol Iterations", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_depth;
    strncpy(l2prod->name_prefix, "depth", UNITLEN);
    strncpy(l2prod->units, "meters", UNITLEN);
    strncpy(l2prod->title, "Water depth", TITLELEN);
    strncpy(l2prod->standard_name, "depth", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flh;
    strncpy(l2prod->name_prefix, "flh", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title, "Fluorescence Line Height", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fsat;
    strncpy(l2prod->name_prefix, "fsat", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title, "Normalized Fluorescence Line Height", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fsat;
    strncpy(l2prod->name_prefix, "nflh", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title, "Normalized Fluorescence Line Height", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fsat2;
    strncpy(l2prod->name_prefix, "nflh2", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title, "Normalized Fluorescence Line Height", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fdiff;
    strncpy(l2prod->name_prefix, "fdiff", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title, "Normalized Fluorescence Line Height (simple)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fqy;
    strncpy(l2prod->name_prefix, "fqy", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Fluorescence Quantum Yield", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fqy2;
    strncpy(l2prod->name_prefix, "fqy2", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-5;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Fluorescence Quantum Yield, A12", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ipar;
    strncpy(l2prod->name_prefix, "ipar", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-7;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "Ein m^-2 s^-1", UNITLEN);
    strncpy(l2prod->title, "Instantaneous Photosynthetically Available Radiation", TITLELEN);
    strncpy(l2prod->standard_name, "downwelling_photosynthetic_photon_radiance_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ipar2;
    strncpy(l2prod->name_prefix, "ipar2", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1e-6;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "Ein m^-2 s^-1", UNITLEN);
    strncpy(l2prod->title, "Instantaneous Photosynthetically Available Radiation", TITLELEN);
    strncpy(l2prod->standard_name, "downwelling_photosynthetic_photon_radiance_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_par;
    strncpy(l2prod->name_prefix, "par", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.002;
    l2prod->offset = 65.5;
    strncpy(l2prod->units, "Ein m^-2 day^-1", UNITLEN);
    strncpy(l2prod->title, "Photosynthetically Available Radiation, R. Frouin", TITLELEN);
    strncpy(l2prod->standard_name, "surface_downwelling_photosynthetic_photon_flux_in_air", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_KD2;
    strncpy(l2prod->name_prefix, "Kd_490", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "KD2", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 490 nm, KD2 algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_KD2;
    strncpy(l2prod->name_prefix, "Kd_490_KD2", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "KD2", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 490 nm, KD2 algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_obpg;
    strncpy(l2prod->name_prefix, "K_490", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "OBPG", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 490 nm (OBPG)", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_obpg;
    strncpy(l2prod->name_prefix, "Kd_490_obpg", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "OBPG", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 490 nm (OBPG)", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_mueller;
    strncpy(l2prod->name_prefix, "Kd_490_mueller", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "mueller", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 490 nm", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_532;
    strncpy(l2prod->name_prefix, "Kd_532", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "532nm", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Diffuse attenuation coefficient at 532 nm", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_lee;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "Kd_", UNITLEN);
    strncpy(l2prod->name_suffix, "_lee", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    l2prod->min = 0.01;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Diffuse attenuation coefficient at %3d nm, Lee Algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Kd_morel;
    strncpy(l2prod->name_prefix, "Kd_490_morel", UNITLEN);
    strncpy(l2prod->product_id, "Kd", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    l2prod->min = 0.01;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Kd(490) Morel Eq8", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_radiative_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_KPAR_morel;
    strncpy(l2prod->name_prefix, "Kd_PAR_morel", UNITLEN);
    strncpy(l2prod->product_id, "Kd_PAR", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->prod_ix = 1;
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    l2prod->min = 0.01;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "K(PAR) Morel (1st optical depth)", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_photosynthetic_photon_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_KPAR_lee;
    strncpy(l2prod->name_prefix, "Kd_PAR_lee", UNITLEN);
    strncpy(l2prod->product_id, "Kd_PAR", UNITLEN);
    strncpy(l2prod->algorithm_id, "lee", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0002;
    l2prod->offset = 0.0;
    l2prod->min = 0.01;
    l2prod->max = 5.0;
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "K(PAR) Lee (1st optical depth)", TITLELEN);
    strncpy(l2prod->standard_name, "diffuse_attenuation_coefficient_of_downwelling_photosynthetic_photon_flux_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zsd_gbr;
    strncpy(l2prod->name_prefix, "Zsd_gbr", UNITLEN);
    strncpy(l2prod->product_id, "Zsd", UNITLEN);
    strncpy(l2prod->algorithm_id, "gbr", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Secchi depth, GBR algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "secchi_depth_of_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zphotic_lee;
    strncpy(l2prod->name_prefix, "Zsd_lee", UNITLEN);
    strncpy(l2prod->product_id, "Zsd", UNITLEN);
    strncpy(l2prod->algorithm_id, "lee", UNITLEN);
    l2prod->prod_ix = -1;
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Secchi depth, Lee algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "secchi_depth_of_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zphotic_lee;
    strncpy(l2prod->name_prefix, "Zeu_lee", UNITLEN);
    strncpy(l2prod->product_id, "Zeu", UNITLEN);
    strncpy(l2prod->algorithm_id, "lee", UNITLEN);
    l2prod->prod_ix = -2;
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Euphotic depth, Lee algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "euphotic_depth_of_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zphotic_lee;
    l2prod->param_type = PARAM_TYPE_INT;
    strncpy(l2prod->name_prefix, "Zp_", UNITLEN);
    strncpy(l2prod->name_suffix, "_lee", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title_format, "Photic depth at %d percent light, Lee algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "euphotic_depth_of_sea_water_at_X_percentage", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zhl_morel;
    strncpy(l2prod->name_prefix, "Zhl_morel", UNITLEN);
    strncpy(l2prod->product_id, "Zhl", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Heated layer depth, Morel algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "depth_of_heating_layer_of _seawater", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zeu_morel;
    strncpy(l2prod->name_prefix, "Zeu_morel", UNITLEN);
    strncpy(l2prod->product_id, "Zeu", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Euphotic depth, Morel algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "euphotic_depth_of_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Zsd_morel;
    strncpy(l2prod->name_prefix, "Zsd_morel", UNITLEN);
    strncpy(l2prod->product_id, "Zsd", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 160.0;
    strncpy(l2prod->units, "m", UNITLEN);
    strncpy(l2prod->title, "Secchi depth, Morel algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "secchi_depth_of_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_morel;
    l2prod->param_type = PARAM_TYPE_INT;
    strncpy(l2prod->name_prefix, "adg_", UNITLEN);
    strncpy(l2prod->name_suffix, "_morel", UNITLEN);
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title_format, "Absorption due to gelbstof and detrital material at %3d nm, Morel 2009 CDOM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_morel;
    strncpy(l2prod->name_prefix, "chl_morel", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    strncpy(l2prod->units, "mg m^3", UNITLEN);
    strncpy(l2prod->title, "Chlorphyll concentration, Morel 2009 CDOM algorithm", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_iCDOM_morel;
    strncpy(l2prod->name_prefix, "cdom_index_morel", UNITLEN);
    strncpy(l2prod->product_id, "cdom_index", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-4;
    l2prod->offset = 6.4;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "CDOM index, Morel 2009 algorithm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_iCDOM_morel;
    strncpy(l2prod->name_prefix, "cdom_index", UNITLEN);
    strncpy(l2prod->product_id, "cdom_index", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-4;
    l2prod->offset = 6.4;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "CDOM index, Morel 2009 algorithm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_pCDOM_morel;
    strncpy(l2prod->name_prefix, "cdom_percent_morel", UNITLEN);
    strncpy(l2prod->product_id, "cdom_percent", UNITLEN);
    strncpy(l2prod->algorithm_id, "morel", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "percent CDOM, Morel 2009 algorithm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_err;
    strncpy(l2prod->name_prefix, "chl_error", UNITLEN);
    l2prod->prod_ix = 1;
    strncpy(l2prod->units, "percent", UNITLEN);
    strncpy(l2prod->title, "Relative error in chlorophyll", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_owtd;
    strncpy(l2prod->name_prefix, "owtd", UNITLEN);
    l2prod->prod_ix = 1;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Dominant optical water type", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_owt;
    l2prod->param_type = PARAM_TYPE_INT;
    strncpy(l2prod->name_prefix, "owt_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Optical water type %d", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_owtn;
    l2prod->param_type = PARAM_TYPE_INT;
    strncpy(l2prod->name_prefix, "owtn_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Normalized optical water type %d", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ndvi;
    strncpy(l2prod->name_prefix, "ndvi", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Normalized Difference Vegetation Index", TITLELEN);
    strncpy(l2prod->standard_name, "normalized_difference_vegetation_index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_evi;
    strncpy(l2prod->name_prefix, "evi", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Enhanced Vegetation Index", TITLELEN);
    strncpy(l2prod->standard_name, "normalized_difference_vegetation_index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_smoke;
    strncpy(l2prod->name_prefix, "smoke", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Smoke Index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aer_model;
    strncpy(l2prod->name_prefix, "aer_model_min", UNITLEN);
    l2prod->prod_ix = 1;
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Lower Bounding Aerosol Model Index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aer_model;
    strncpy(l2prod->name_prefix, "aer_model_max", UNITLEN);
    l2prod->prod_ix = 2;
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Upper Bounding Aerosol Model Index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aer_ratio;
    strncpy(l2prod->name_prefix, "aer_model_ratio", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol Model Interpolation Ratio", TITLELEN);

//    l2prod = createNewProduct();
//    l2prod->cat_ix = CAT_epsilon;
//    strncpy(l2prod->name_prefix, "epsilon", UNITLEN);
//    l2prod->datatype = DFNT_INT16;
//    l2prod->slope = 5e-5;
//    l2prod->offset = 1.6;
//    strncpy(l2prod->units, "dimensionless", UNITLEN);
//    strncpy(l2prod->title, "Single-scattering aerosol epsilon", TITLELEN);
//20180829  NCDF
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_epsilon;
    strncpy(l2prod->name_prefix, "eps78", UNITLEN);
    l2prod->datatype = DFNT_FLOAT32;
    l2prod->slope = 1.0;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Single-scattering aerosol epsilon", TITLELEN);


    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ms_epsilon;
    strncpy(l2prod->name_prefix, "ms_epsilon", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    sprintf(l2prod->title, "Observed (multi-scattering) aerosol epsilon");

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Lw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "Lw_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = -1;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Water-leaving radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "surface_upwelling_radiance_in_air_emerging_from_sea_water", TITLELEN);

//    l2prod = createNewProduct();
//    l2prod->cat_ix = CAT_nLw;
//    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
//    strncpy(l2prod->name_prefix, "nLw_", UNITLEN);
//    l2prod->datatype = DFNT_INT16;
//    l2prod->slope = -1;
//    l2prod->offset = 0.0;
//    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
//    strncpy(l2prod->title_format, "Normalized water-leaving radiance at %3d nm", TITLELEN);
//    strncpy(l2prod->standard_name, "normalized_surface_upwelling_radiance_in_air_emerging_from_sea_water", TITLELEN);
//   //////20180829  NCDF format required
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_nLw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "nLw", UNITLEN);
    l2prod->datatype = DFNT_FLOAT32;
    l2prod->slope = 1.0;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Normalized water-leaving radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "normalized_surface_upwelling_radiance_in_air_emerging_from_sea_water", TITLELEN);




    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_nLw_unc;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "nLw_unc_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = -1;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in normalized water-leaving radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_rhos;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "rhos_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Surface reflectance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "surface_albedo", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_rhom;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "rhom_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Water + aerosol reflectance at %3d nm (MUMM)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_rhot;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "rhot_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Top-of-atmosphere reflectance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_albedo", TITLELEN);

//    l2prod = createNewProduct();
//    l2prod->cat_ix = CAT_Rrs;
//    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
//    strncpy(l2prod->name_prefix, "Rrs_", UNITLEN);
//    l2prod->datatype = DFNT_INT16;
//    l2prod->slope = 0.000002;
//    l2prod->offset = 0.05;
//    strncpy(l2prod->units, "sr^-1", UNITLEN);
//    strncpy(l2prod->title_format, "Remote sensing reflectance at %3d nm", TITLELEN);
//   20180829 NCDF
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "Rrs", UNITLEN);
    l2prod->datatype = DFNT_FLOAT32;
    l2prod->slope = 1.0;
    l2prod->offset =0.0;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance at %3d nm", TITLELEN);



    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_unc;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "Rrs_unc_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Uncertainty in remote sensing reflectance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 0;
    strncpy(l2prod->name_prefix, "Rrs_vc_412", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 412 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 1;
    strncpy(l2prod->name_prefix, "Rrs_vc_443", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 443 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 2;
    strncpy(l2prod->name_prefix, "Rrs_vc_490", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 490 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 3;
    strncpy(l2prod->name_prefix, "Rrs_vc_510", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 510 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 4;
    strncpy(l2prod->name_prefix, "Rrs_vc_531", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 531 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 5;
    strncpy(l2prod->name_prefix, "Rrs_vc_555", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 555 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrs_vc;
    l2prod->prod_ix = 6;
    strncpy(l2prod->name_prefix, "Rrs_vc_670", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.000002;
    l2prod->offset = 0.05;
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Remote sensing reflectance, virtual constellation at 670 nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl_vc;
    strncpy(l2prod->name_prefix, "chl_vc", UNITLEN);
    strncpy(l2prod->product_id, "chlor_a", UNITLEN);
    strncpy(l2prod->algorithm_id, "oc3", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, OC3 Algorithm, VC-tuned", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

//    l2prod = createNewProduct();
//    l2prod->cat_ix = CAT_La;
//    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
//    strncpy(l2prod->name_prefix, "La_", UNITLEN);
//    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
//    strncpy(l2prod->title_format, "Aerosol radiance at %3d nm", TITLELEN);
//    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_aerosols", TITLELEN);
//20180829 NCDF
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_La;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "la", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Aerosol radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_aerosols", TITLELEN);



    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Taua;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "aot_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Aerosol optical thickness at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "atmosphere_absorption_optical_thickness_due_to_ambient_aerosol", TITLELEN);

//    l2prod = createNewProduct();
//    l2prod->cat_ix = CAT_Taua;
//    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
//    strncpy(l2prod->name_prefix, "taua_", UNITLEN);
//    l2prod->datatype = DFNT_INT16;
//    l2prod->slope = 0.0001;
//    l2prod->offset = 0.0;
//    strncpy(l2prod->units, "dimensionless", UNITLEN);
//    strncpy(l2prod->title_format, "Aerosol optical thickness at %3d nm", TITLELEN);
//    strncpy(l2prod->standard_name, "atmosphere_absorption_optical_thickness_due_to_ambient_aerosol", TITLELEN);
//20180829 NCDF
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Taua;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "taua", UNITLEN);
    l2prod->datatype = DFNT_FLOAT32;
    l2prod->slope = 1.0;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Aerosol optical thickness at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "atmosphere_absorption_optical_thickness_due_to_ambient_aerosol", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Taua;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "tau_", UNITLEN);
    strncpy(l2prod->product_id, "taua", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Aerosol optical thickness at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "atmosphere_absorption_optical_thickness_due_to_ambient_aerosol", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_angstrom;
    strncpy(l2prod->name_prefix, "angstrom", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol Angstrom exponent, 443 to 865 nm", TITLELEN);
    strncpy(l2prod->standard_name, "aerosol_angstrom_exponent", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_angstrom;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "angstrom_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.0001;
    l2prod->offset = 2.5;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Aerosol Angstrom exponent, %d to 865 nm", TITLELEN);
    strncpy(l2prod->standard_name, "aerosol_angstrom_exponent", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_TLg;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "TLg_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "TOA glint radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_specular_reflection", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Lr;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "Lr_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Rayleigh radiance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_rayliegh_scattering", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_L_q;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "L_q_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Polarization radiance at %3d nm, q-component", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_Stokes_Q_component", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_L_u;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "L_u_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "Polarization radiance at %3d nm, u-component", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_Stokes_U_component", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_polcor;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "polcor_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Polarization correction at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Es;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "Es_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1", UNITLEN);
    strncpy(l2prod->title_format, "Solar Irradiance at Surface at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "surface_downwelling_spectral_spherical_irradiance_in_sea_water", TITLELEN);

    /* Allow alternate name brdf to mean brdf_412. brdf is spectrally independent
       for sensors with common view geometry in each band, for Fresnel or Rgoth */
    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_brdf;
    strncpy(l2prod->name_prefix, "brdf", UNITLEN);
    l2prod->prod_ix = 0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "BRDF correction", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_brdf;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "brdf_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "BRDF correction at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tLf;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "tLf_", UNITLEN);
    strncpy(l2prod->units, "mW cm^-2 um^-1 sr^-1", UNITLEN);
    strncpy(l2prod->title_format, "White-cap radiance at TOA at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "toa_upwelling_radiance_from_sea_foam", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_t_sol;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "t_sol_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Rayleigh-Aerosol Diff. Trans., Sun to Surface, at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_t_sen;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "t_sen_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Rayleigh-Aerosol Diff. Trans., Surface to Sensor, at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tg_sol;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "tg_sol_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Gaseous Transmittance, Sun to Surface, at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tg_sen;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "tg_sen_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Gaseous Transmittance, Surface to Sensor, at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_t_h2o;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "t_h2o_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Total water vapor transmittance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_t_o2;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "t_o2_", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.00005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Total oxygen transmittance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_dpol;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "dpol_", UNITLEN);
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Degree of Rayleigh Polarization at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_fsol;
    strncpy(l2prod->name_prefix, "fsol", UNITLEN);
    l2prod->datatype = DFNT_FLOAT64;
    l2prod->rank = 1;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Solar distance correction factor", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_pixnum;
    strncpy(l2prod->name_prefix, "pixnum", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Scan Pixel Number (zero-based)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_detnum;
    strncpy(l2prod->name_prefix, "detnum", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    l2prod->rank = 1;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Detector Number (zero-based)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_mside;
    strncpy(l2prod->name_prefix, "mside", UNITLEN);
    l2prod->datatype = DFNT_INT32;
    l2prod->rank = 1;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Mirror Side (zero-based)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_solz;
    strncpy(l2prod->name_prefix, "solz", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1.0 / 360.0;
    l2prod->offset = 90.0;
    l2prod->min = 0;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Solar Zenith Angle", TITLELEN);
    strncpy(l2prod->standard_name, "solar_zenith_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sola;
    strncpy(l2prod->name_prefix, "sola", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1.0 / 90.0;
    l2prod->offset = 0.0;
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Solar Azimuth Angle", TITLELEN);
    strncpy(l2prod->standard_name, "solar_azimuth_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_senz;
    strncpy(l2prod->name_prefix, "senz", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1.0 / 360.0;
    l2prod->offset = 90.0;
    l2prod->min = 0;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Sensor Zenith Angle", TITLELEN);
    strncpy(l2prod->standard_name, "sensor_zenith_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sena;
    strncpy(l2prod->name_prefix, "sena", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1.0 / 90.0;
    l2prod->offset = 0.0;
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Sensor Azimuth Angle", TITLELEN);
    strncpy(l2prod->standard_name, "sensor_azimuth_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_relaz;
    strncpy(l2prod->name_prefix, "relaz", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 1.0 / 90.0;
    l2prod->offset = 0.0;
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Relative Azimuth Angle", TITLELEN);
    strncpy(l2prod->standard_name, "relative_solar_to_sensor_azimuth_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_scattang;
    strncpy(l2prod->name_prefix, "scattang", UNITLEN);
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Scattering Angle", TITLELEN);
    strncpy(l2prod->standard_name, "scattering_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_alpha;
    strncpy(l2prod->name_prefix, "alpha", UNITLEN);
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degree", UNITLEN);
    strncpy(l2prod->title, "Polarization Rotation Angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ozone;
    strncpy(l2prod->name_prefix, "ozone", UNITLEN);
    strncpy(l2prod->units, "cm", UNITLEN);
    strncpy(l2prod->title, "Ozone Concentration", TITLELEN);
    strncpy(l2prod->standard_name, "equivalent_thickness_at_stp_of_atmosphere_ozone_content", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_pressure;
    strncpy(l2prod->name_prefix, "pressure", UNITLEN);
    strncpy(l2prod->units, "millibars", UNITLEN);
    strncpy(l2prod->title, "Surface Pressure", TITLELEN);
    strncpy(l2prod->standard_name, "air_pressure_at_sea_level", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_windspeed;
    strncpy(l2prod->name_prefix, "windspeed", UNITLEN);
    strncpy(l2prod->units, "m s^-1", UNITLEN);
    strncpy(l2prod->title, "Wind Speed at 10 meters", TITLELEN);
    strncpy(l2prod->standard_name, "wind_speed", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_mwind;
    strncpy(l2prod->name_prefix, "mwind", UNITLEN);
    strncpy(l2prod->units, "m s^-1", UNITLEN);
    strncpy(l2prod->title, "Meridional Wind Speed at 10 meters", TITLELEN);
    strncpy(l2prod->standard_name, "eastward_wind", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_zwind;
    strncpy(l2prod->name_prefix, "zwind", UNITLEN);
    strncpy(l2prod->units, "m s^-1", UNITLEN);
    strncpy(l2prod->title, "Zonal Wind Speed at 10 meters", TITLELEN);
    strncpy(l2prod->standard_name, "northward_wind", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_windangle;
    strncpy(l2prod->name_prefix, "windangle", UNITLEN);
    l2prod->min = -180;
    l2prod->max = 180;
    strncpy(l2prod->units, "degrees", UNITLEN);
    strncpy(l2prod->title, "Wind direction at 10 meters", TITLELEN);
    strncpy(l2prod->standard_name, "wind_angle", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_water_vapor;
    strncpy(l2prod->name_prefix, "water_vapor", UNITLEN);
    strncpy(l2prod->units, "g cm^-2", UNITLEN);
    strncpy(l2prod->title, "Water Vapor", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_height;
    strncpy(l2prod->name_prefix, "height", UNITLEN);
    strncpy(l2prod->units, "meters", UNITLEN);
    strncpy(l2prod->title, "Terrain Height", TITLELEN);
    strncpy(l2prod->standard_name, "height", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_humidity;
    strncpy(l2prod->name_prefix, "humidity", UNITLEN);
    strncpy(l2prod->units, "%", UNITLEN);
    strncpy(l2prod->title, "Relative Humidity", TITLELEN);
    strncpy(l2prod->standard_name, "relative_humidity", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_no2_tropo;
    strncpy(l2prod->name_prefix, "no2_tropo", UNITLEN);
    strncpy(l2prod->units, "molecules cm^-2", UNITLEN);
    strncpy(l2prod->title, "Tropospheric NO2", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_no2_strat;
    strncpy(l2prod->name_prefix, "no2_strat", UNITLEN);
    strncpy(l2prod->units, "molecules cm^-2", UNITLEN);
    strncpy(l2prod->title, "Stratospheric NO2", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_no2_frac;
    strncpy(l2prod->name_prefix, "no2_frac", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Fraction of tropospheric NO2 above 200 m", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_glint_coef;
    strncpy(l2prod->name_prefix, "glint_coef", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Cox-Munk normalized glint radiance", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_cloud_albedo;
    strncpy(l2prod->name_prefix, "cloud_albedo", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Cloud albedo used for thresholding", TITLELEN);
    strncpy(l2prod->standard_name, "cloud_albedo", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_rho_cirrus;
    strncpy(l2prod->name_prefix, "rho_cirrus", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Cirrus reflectance (1380 nm)", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_aerindex;
    strncpy(l2prod->name_prefix, "aerindex", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol Index", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tindx_morel;
    strncpy(l2prod->name_prefix, "tindx_morel", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Turbidity Index Morel", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tindx_shi;
    strncpy(l2prod->name_prefix, "tindx_shi", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Turbidity Index Shi and Wang", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_BT_39;
    strncpy(l2prod->name_prefix, "BT_39", UNITLEN);
    l2prod->prod_ix = 1;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Brightness Temperature at 3.9 um", TITLELEN);
    strncpy(l2prod->standard_name, "brightness_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_BT_40;
    strncpy(l2prod->name_prefix, "BT_40", UNITLEN);
    l2prod->prod_ix = 2;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Brightness Temperature at 4.0 um", TITLELEN);
    strncpy(l2prod->standard_name, "brightness_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_BT_11;
    strncpy(l2prod->name_prefix, "BT_11", UNITLEN);
    l2prod->prod_ix = 6;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Brightness Temperature at 11 um", TITLELEN);
    strncpy(l2prod->standard_name, "brightness_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_BT_12;
    strncpy(l2prod->name_prefix, "BT_12", UNITLEN);
    l2prod->prod_ix = 7;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Brightness Temperature at 12 um", TITLELEN);
    strncpy(l2prod->standard_name, "brightness_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sst;
    strncpy(l2prod->name_prefix, "sst", UNITLEN);
    strncpy(l2prod->product_id, "sst", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Sea Surface Temperature", TITLELEN);
    strncpy(l2prod->standard_name, "sea_surface_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sst4;
    strncpy(l2prod->name_prefix, "sst4", UNITLEN);
    strncpy(l2prod->product_id, "sst", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst4", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "4um Sea Surface Temperature", TITLELEN);
    strncpy(l2prod->standard_name, "sea_surface_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_sst;
    strncpy(l2prod->name_prefix, "flags_sst", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags, Sea Surface Temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_flags_sst4;
    strncpy(l2prod->name_prefix, "flags_sst4", UNITLEN);
    strncpy(l2prod->product_id, "flags", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst4", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Product-specific flags, 4um Sea Surface Temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_qual_sst;
    strncpy(l2prod->name_prefix, "qual_sst", UNITLEN);
    strncpy(l2prod->product_id, "qual", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst", UNITLEN);
    l2prod->datatype = DFNT_INT8;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Quality Levels, Sea Surface Temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_qual_sst4;
    strncpy(l2prod->name_prefix, "qual_sst4", UNITLEN);
    strncpy(l2prod->product_id, "qual", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst4", UNITLEN);
    l2prod->datatype = DFNT_INT8;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Quality Levels, Sea Surface Temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bias_sst;
    strncpy(l2prod->name_prefix, "bias_sst", UNITLEN);
    strncpy(l2prod->product_id, "bias", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst", UNITLEN);
    l2prod->datatype = DFNT_UINT8;
    l2prod->slope = 0.15;
    l2prod->offset = -19;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Sea Surface Temperature Bias", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_bias_sst4;
    strncpy(l2prod->name_prefix, "bias_sst4", UNITLEN);
    strncpy(l2prod->product_id, "bias", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst4", UNITLEN);
    l2prod->datatype = DFNT_UINT8;
    l2prod->slope = 0.15;
    l2prod->offset = -19;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "4um Sea Surface Temperature Bias", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_stdv_sst;
    strncpy(l2prod->name_prefix, "stdv_sst", UNITLEN);
    strncpy(l2prod->product_id, "stdv", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst", UNITLEN);
    l2prod->datatype = DFNT_UINT8;
    l2prod->slope = 0.15;
    l2prod->offset = -19;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Sea Surface Temperature Standard Deviation", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_stdv_sst4;
    strncpy(l2prod->name_prefix, "stdv_sst4", UNITLEN);
    strncpy(l2prod->product_id, "stdv", UNITLEN);
    strncpy(l2prod->algorithm_id, "sst4", UNITLEN);
    l2prod->datatype = DFNT_UINT8;
    l2prod->slope = 0.15;
    l2prod->offset = -19;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "4um Sea Surface Temperature Standard Deviation", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sstref;
    strncpy(l2prod->name_prefix, "sstref", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "degrees-C", UNITLEN);
    strncpy(l2prod->title, "Sea Surface Temperature Reference", TITLELEN);
    strncpy(l2prod->standard_name, "sea_surface_temperature", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_sssref;
    strncpy(l2prod->name_prefix, "sssref", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 0.005;
    l2prod->offset = 0.0;
    strncpy(l2prod->units, "psu", UNITLEN);
    strncpy(l2prod->title, "Sea Surface Salinity Reference", TITLELEN);
    strncpy(l2prod->standard_name, "sea_surface_salinity", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_calcite;
    strncpy(l2prod->name_prefix, "pic", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-6;
    l2prod->offset = 0.065;
    strncpy(l2prod->units, "mol m^-3", UNITLEN);
    strncpy(l2prod->title, "Calcite Concentration, Balch and Gordon", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_inorganic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_calcite;
    strncpy(l2prod->name_prefix, "calcite", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-6;
    l2prod->offset = 0.065;
    strncpy(l2prod->units, "mol m^-3", UNITLEN);
    strncpy(l2prod->title, "Calcite Concentration, Balch and Gordon", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_inorganic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_calcite_2b;
    strncpy(l2prod->name_prefix, "calcite_2b", UNITLEN);
    strncpy(l2prod->product_id, "calcite", UNITLEN);
    strncpy(l2prod->algorithm_id, "2band", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-6;
    l2prod->offset = 0.065;
    strncpy(l2prod->units, "mol m^-3", UNITLEN);
    strncpy(l2prod->title, "Calcite Concentration, 2-Band Algorithm, H. R. Gordon et al.", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_inorganic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_calcite_3b;
    strncpy(l2prod->name_prefix, "calcite_3b", UNITLEN);
    strncpy(l2prod->product_id, "calcite", UNITLEN);
    strncpy(l2prod->algorithm_id, "3band", UNITLEN);
    l2prod->datatype = DFNT_INT16;
    l2prod->slope = 2e-6;
    l2prod->offset = 0.065;
    strncpy(l2prod->units, "mol m^-3", UNITLEN);
    strncpy(l2prod->title, "Calcite Concentration, 3-Band Algorithm, H. R. Gordon et al.", TITLELEN);
    strncpy(l2prod->standard_name, "mole_concentration_of_particulate_inorganic_carbon_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vgain;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vgain_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious gain at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vLt;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vLt_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious TOA radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vtLw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vtLw_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious TOA water-leaving radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vLw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vLw_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious water-leaving radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vnLw;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vnLw_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious normalized water-leaving radiance at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vbsat;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vbsat_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious BRDF for satellite at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_vbtgt;
    l2prod->param_type = PARAM_TYPE_VIS_WAVE;
    strncpy(l2prod->name_prefix, "vbtgt_", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title_format, "Vicarious BRDF for target at %3d nm", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod1;
    strncpy(l2prod->name_prefix, "myprod1", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 1", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod2;
    strncpy(l2prod->name_prefix, "myprod2", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 2", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod3;
    strncpy(l2prod->name_prefix, "myprod3", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 3", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod4;
    strncpy(l2prod->name_prefix, "myprod4", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 4", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod5;
    strncpy(l2prod->name_prefix, "myprod5", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 5", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod6;
    strncpy(l2prod->name_prefix, "myprod6", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 6", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod7;
    strncpy(l2prod->name_prefix, "myprod7", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 7", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod8;
    strncpy(l2prod->name_prefix, "myprod8", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 8", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod9;
    strncpy(l2prod->name_prefix, "myprod9", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 9", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_myprod10;
    strncpy(l2prod->name_prefix, "myprod10", UNITLEN);
    strncpy(l2prod->units, "unspecified", UNITLEN);
    strncpy(l2prod->title, "User-Defined Product 10", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl1_meris;
    strncpy(l2prod->name_prefix, "chl1_meris", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, MERIS L2 algal_1", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_chl2_meris;
    strncpy(l2prod->name_prefix, "chl2_meris", UNITLEN);
    strncpy(l2prod->units, "mg m^-3", UNITLEN);
    strncpy(l2prod->title, "Chlorophyll Concentration, MERIS L2 algal_2", TITLELEN);
    strncpy(l2prod->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_adg_meris;
    strncpy(l2prod->name_prefix, "adg_meris", UNITLEN);
    strncpy(l2prod->units, "m^-1", UNITLEN);
    strncpy(l2prod->title, "Yellow Substance, MERIS L2 yellow_subs", TITLELEN);
    strncpy(l2prod->standard_name, "volume_absorption_coefficient_of_radiative_flux_in_sea_water_due_to_dissolved_organic_matter", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_tsm_meris;
    strncpy(l2prod->name_prefix, "tsm_meris", UNITLEN);
    strncpy(l2prod->units, "g m^-3", UNITLEN);
    strncpy(l2prod->title, "Total Suspended Matter, MERIS L2 total_susp", TITLELEN);
    strncpy(l2prod->standard_name, "mass_concentration_of_suspended_matter_in_sea_water", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_par_meris;
    strncpy(l2prod->name_prefix, "par_meris", UNITLEN);
    strncpy(l2prod->units, "uEinstein m^-2 s^-1", UNITLEN);
    strncpy(l2prod->title, "Photosynthetically Active Radiation, MERIS L2 photosyn_rad", TITLELEN);
    strncpy(l2prod->standard_name, "surface_downwelling_photosynthetic_photon_flux_in_air", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_angstrom_meris;
    strncpy(l2prod->name_prefix, "angstrom_meris", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol Angstrom Exponent, MERIS L2 aero_alpha", TITLELEN);
    strncpy(l2prod->standard_name, "aerosol_angstrom_exponent", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Taua_meris;
    strncpy(l2prod->name_prefix, "Taua_meris", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Aerosol Optical Thickness, MERIS L2 aero_opt_thick", TITLELEN);
    strncpy(l2prod->standard_name, "atmosphere_absorption_optical_thickness_due_to_ambient_aerosol", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_ice_frac;
    strncpy(l2prod->name_prefix, "ice_frac", UNITLEN);
    l2prod->min = 0;
    l2prod->max = 1;
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "Ice Fraction, 0=no ice, 1=all ice", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_class_ward_owmc;
    strncpy(l2prod->name_prefix, "class_ward_owmc", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "OWMC Ward Classification", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_class_k_owmc;
    strncpy(l2prod->name_prefix, "class_k_owmc", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "OWMC K_means Classification", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_class_34k_w_owmc;
    strncpy(l2prod->name_prefix, "class_34k_w_owmc", UNITLEN);
    strncpy(l2prod->units, "dimensionless", UNITLEN);
    strncpy(l2prod->title, "OWMC merged Wards and K_means (34K+W) Classification", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_log10chl;
    strncpy(l2prod->name_prefix, "log10chl", UNITLEN);
    strncpy(l2prod->units, "log10(mg m^-3)", UNITLEN);
    strncpy(l2prod->title, "log10 of Chlorophyll Concentration", TITLELEN);

    l2prod = createNewProduct();
    l2prod->cat_ix = CAT_Rrc;
    l2prod->param_type = PARAM_TYPE_ALL_WAVE;
    strncpy(l2prod->name_prefix, "Rrc_", UNITLEN);
    strncpy(l2prod->units, "sr^-1", UNITLEN);
    // strncpy(l2prod->title_format, "Calibrated TOA radiance at %3d nm", TITLELEN);
    strncpy(l2prod->title_format, "Rayleigh-corrected Reflectance at %3d nm", TITLELEN);
    strncpy(l2prod->standard_name, "(Rayleigh-corrected Reflectance,Rrc)", TITLELEN);

    // loop through the products and set some default info
    for (i = 0; i < l2prod_num; i++) {
        l2prod = l2prod_array[i];
        if (l2prod->rank == 2) {
            l2prod->dim[0] = numScans;
            l2prod->dim[1] = numPixels;
            l2prod->dim[2] = 1;
            strncpy(l2prod->dimname[0], "Number of Scan Lines", DIMNAMELEN);
            strncpy(l2prod->dimname[1], "Pixels per Scan Line", DIMNAMELEN);
            strncpy(l2prod->dimname[2], "", DIMNAMELEN);
        } else if (l2prod->rank == 1) {
            l2prod->dim[0] = numScans;
            l2prod->dim[1] = 1;
            l2prod->dim[2] = 1;
            strncpy(l2prod->dimname[0], "Number of Scan Lines", DIMNAMELEN);
            strncpy(l2prod->dimname[1], "", DIMNAMELEN);
            strncpy(l2prod->dimname[2], "", DIMNAMELEN);
        }
    }

}


/* -------------------------------------------------------------------------- */

/* -------------------------------------------------------------------------- */
l2prodstr *get_l2prod_index(char *prod_name, /* Input SDS name              */
        int32 sensorID, /* Sensor ID                   */
        int32 numBands, /* Number of Wavelengths       */
        int32 numPixels, /* Number of Pixels per Scan   */
        int32 numScans, /* Number of Scans in File     */
        int32_t wave[]) /* Wavelength Array (numBands) */ {
    int i;
    int prodIndex;
    char tmp_pname[32];
    l2prodstr *p = NULL;

    static int first = 1;
    static int32_t nbands = -1;
    static int default_iprod_chl = -1;
    static l2prodstr* default_prod_chl = NULL;

    if (first) {
        first = 0;

        init_l2prod(numPixels, numScans);

        switch (sensorID) {
            case SEAWIFS:
            case OCTS:
            case OCM1:
            case OCM2:
            case MOS:
            case MERIS:
            case MERISL2:
                default_iprod_chl = CAT_chl_oc4;
                break;
            case MODIST:
            case MODISA:
            case HMODIST:
            case HMODISA:
            case CZCS:
            case OSMI:
            case VIIRS:
            case OCRVC:
                default_iprod_chl = CAT_chl_oc3;
                break;
            default:
//                HY1C_out("%s Line %d: need a default chlorophyll algorithm for this sensor\n",
//                        __FILE__, __LINE__);
                                default_iprod_chl = CAT_chl_oc3;

                exit(1);
                break;
        } // switch

        for (prodIndex = 0; prodIndex < l2prod_num; prodIndex++) {
            p = l2prod_array[prodIndex];
            if (p->cat_ix == default_iprod_chl) {
                default_prod_chl = p;
                break;
            }
        }
        if (default_prod_chl == NULL) {
            HY1C_out("%s Line %d: could not find the default chlorophyll algorithm for this sensor\n",
                    __FILE__, __LINE__);
            exit(1);
        }

        // fix the title of the CDOM-corrected CHL model 
        for (prodIndex = 0; prodIndex < l2prod_num; prodIndex++) {
            p = l2prod_array[prodIndex];
            if (p->cat_ix == CAT_chl_cdomcorr_morel) {
                sprintf(p->title, "%s, CDOM-corrected via Morel",
                        default_prod_chl->title);
                break;
            }
        }

        /* set the number of visable and ir bands */
        for (i = 0; i < numBands; i++)
            if (wave[i] > MINWAVE_IR)
                break;
        nbands = i;

    } // if first


    if (strcmp(prod_name, "chlor_a") == 0) { /* Sensor default chlorophyll-a */
        return default_prod_chl;
    }

    // loop through products until we find a match
    for (prodIndex = 0; prodIndex < l2prod_num; prodIndex++) {
        p = l2prod_array[prodIndex];
        switch (p->param_type) {
            case PARAM_TYPE_NONE:
                if (strcasecmp(prod_name, p->name_prefix) == 0)
                    return p;
                break;

            case PARAM_TYPE_VIS_WAVE:
                for (i = 0; i < nbands; i++) {
                    sprintf(tmp_pname, "%s%d%s", p->name_prefix, wave[i], p->name_suffix);
                    if (strcasecmp(prod_name, tmp_pname) == 0) {
                        p->prod_ix = i;
                        sprintf(p->title, p->title_format, wave[i]);
                        if ((p->cat_ix == CAT_Lw) ||
                                (p->cat_ix == CAT_nLw) ||
                                (p->cat_ix == CAT_nLw_unc) ){
                            if (wave[i] < 600)
                                p->slope = 0.001;
                            else if (wave[i] < 650)
                                p->slope = 0.0005;
                            else
                                p->slope = 0.0001;
                        }
                        return p;
                    }
                }
                break;

            case PARAM_TYPE_IR_WAVE:
                for (i = nbands; i < numBands; i++) {
                    sprintf(tmp_pname, "%s%d%s", p->name_prefix, wave[i], p->name_suffix);
                    if (strcasecmp(prod_name, tmp_pname) == 0) {
                        p->prod_ix = i - nbands;
                        sprintf(p->title, p->title_format, wave[i]);
                        return p;
                    }
                }
                break;

            case PARAM_TYPE_ALL_WAVE:
                for (i = 0; i < numBands; i++) {
                    sprintf(tmp_pname, "%s%d%s", p->name_prefix, wave[i], p->name_suffix);
                    if (strcasecmp(prod_name, tmp_pname) == 0) {
                        p->prod_ix = i;
                        sprintf(p->title, p->title_format, wave[i]);
                        return p;
                    }
                }
                break;

            case PARAM_TYPE_BAND:
                for (i = 0; i < numBands; i++) {
                    sprintf(tmp_pname, "%s%d%s", p->name_prefix, i+1, p->name_suffix);
                    if (strcasecmp(prod_name, tmp_pname) == 0) {
                        p->prod_ix = i;
                        sprintf(p->title, p->title_format, i);
                        return p;
                    }
                }
                break;

            case PARAM_TYPE_INT:
                if (p->name_suffix[0] == 0) {
                    if (strncasecmp(prod_name, p->name_prefix, strlen(p->name_prefix)) == 0) {
                        p->prod_ix = atoi(&prod_name[strlen(p->name_prefix)]);
                        sprintf(p->title, p->title_format, p->prod_ix);
                        return p;
                    }
                } else {
                    if ((strncasecmp(prod_name, p->name_prefix, strlen(p->name_prefix)) == 0) &&
                            (strcasecmp(prod_name + strlen(prod_name) - strlen(p->name_suffix), p->name_suffix) == 0)) {
                        p->prod_ix = atoi(&prod_name[strlen(p->name_prefix)]);
                        sprintf(p->title, p->title_format, p->prod_ix);
                        return p;
                    }
                } // prefix and suffix
                break;

        } // switch

    } // for product list

    fHY1C_out(stderr, "\n%s - Invalid product name : %s\n", __FILE__, prod_name);
    exit(1);
}

/* read the product structure and copy the product name into productName */
void getProductName(char* name, l2prodstr* product) {
    if (product->product_id[0] != '\0') {
        strcpy(name, product->product_id);
    } else {
        strcpy(name, product->name_prefix);

        // remove trailing underscore
        if (name[strlen(name) - 1] == '_') {
            name[strlen(name) - 1] = '\0';
        }
    }
}

/* read the product structure and copy the algorithm name into name */
void getAlgorithmName(char* name, l2prodstr* product) {
    int i;
    int length;

    if (product->algorithm_id[0] != '\0') {
        strcpy(name, product->algorithm_id);
    } else {
        strcpy(name, product->name_suffix);

        // remove leading underscore
        if (name[0] == '_') {
            length = strlen(name);
            for (i = 1; i <= length; i++) {
                name[i - 1] = name[i];
            }
        }
    }
}

/* read the product structure and copy the product name into productName */
void getParamType(char* name, l2prodstr* product) {
    switch (product->param_type) {
        case PARAM_TYPE_NONE:
            strcpy(name, "None");
            break;
        case PARAM_TYPE_VIS_WAVE:
            strcpy(name, "Visible");
            break;
        case PARAM_TYPE_IR_WAVE:
            strcpy(name, "IR");
            break;
        case PARAM_TYPE_ALL_WAVE:
            strcpy(name, "All");
            break;
        case PARAM_TYPE_BAND:
            strcpy(name, "Bands");
            break;
        case PARAM_TYPE_INT:
            strcpy(name, "Integer");
            break;
        default:
            strcpy(name, "Unknown");
            break;
    }
}

/* read the product structure and copy the product name into productName */
void getDataType(char* name, l2prodstr* product) {
    switch (product->datatype) {
        case DFNT_INT8:
            strcpy(name, "INT8");
            break;
        case DFNT_INT16:
            strcpy(name, "INT16");
            break;
        case DFNT_INT32:
            strcpy(name, "INT32");
            break;
        case DFNT_FLOAT32:
            strcpy(name, "FLOAT32");
            break;
        case DFNT_FLOAT64:
            strcpy(name, "FLOAT64");
            break;
        default:
            strcpy(name, "Unknown");
            break;
    }
}

void setTitleString(l2prodstr* product) {
    switch (product->param_type) {
        case PARAM_TYPE_NONE:
            break;
        case PARAM_TYPE_VIS_WAVE:
        case PARAM_TYPE_IR_WAVE:
        case PARAM_TYPE_ALL_WAVE:
        case PARAM_TYPE_BAND:
        case PARAM_TYPE_INT:
            sprintf(product->title, product->title_format, 0);
            break;
    }
}

/* dump the product list to a file */
void dumpProductStructure(l2prodstr **list, FILE* fout) {
    l2prodstr* product;
    int productIndex;
    char productName[UNITLEN];
    char algorithmName[UNITLEN];
    char paramType[UNITLEN];

    for (productIndex = 0; productIndex < l2prod_num; productIndex++) {
        product = list[productIndex];
        getProductName(productName, product);
        getAlgorithmName(algorithmName, product);
        getParamType(paramType, product);

        fHY1C_out(fout, "%s, %s, %s, %d\n", productName, algorithmName, paramType, product->cat_ix);
    }
}

void XML_file_header(FILE* fout) {
    fHY1C_out(fout, "<productList>\n");
}

void XML_file_footer(FILE* fout) {
    fHY1C_out(fout, "</productList>\n");
}

void XML_product_header(FILE* fout, l2prodstr* product) {
    char name[UNITLEN];

    getProductName(name, product);
    fHY1C_out(fout, "    <product name=\"%s\">\n", name);
}

void XML_product_footer(FILE* fout) {
    fHY1C_out(fout, "    </product>\n");
}

void XML_algorithm(FILE* fout, l2prodstr* product) {
    char name[UNITLEN];
    char param[UNITLEN];
    char data[UNITLEN];

    getAlgorithmName(name, product);
    getParamType(param, product);
    getDataType(data, product);
    setTitleString(product);

    if (strlen(name) > 0) {
        fHY1C_out(fout, "        <algorithm name=\"%s\">\n", name);
    } else {
        fHY1C_out(fout, "        <algorithm>\n");
    }
    clo_writeXmlTag(fout, 3, "prefix", product->name_prefix);
    clo_writeXmlTag(fout, 3, "suffix", product->name_suffix);
    clo_writeXmlTag(fout, 3, "parameterType", param);
    clo_writeXmlTag(fout, 3, "dataType", data);
    clo_writeXmlTag(fout, 3, "units", product->units);
    clo_writeXmlTag(fout, 3, "description", product->title);
    fHY1C_out(fout, "        </algorithm>\n");
}

void write_product_XML_file(char* filename) {
    l2prodstr **tmpList = NULL; // array of pointers to all the products
    l2prodstr **sortedList = NULL; // array of pointers to all the products
    int sortedIndex = 0; // number of products in the array
    l2prodstr* product;
    l2prodstr* product2;
    static l2prodstr *chlProd;
    char productName[UNITLEN];
    char productName2[UNITLEN];
    int productIndex;
    int productIndex2;
    FILE* fout;
    int i;

    if(chlProd==NULL) {
        // allocate the structure
        chlProd = (l2prodstr*) malloc(sizeof (l2prodstr));
        initProduct(chlProd);
        
        chlProd->cat_ix = CAT_chl_oc2;
        strncpy(chlProd->name_prefix, "chlor_a", UNITLEN);
        strncpy(chlProd->product_id, "chlor_a", UNITLEN);
        strncpy(chlProd->algorithm_id, "chlor_a", UNITLEN);
        strncpy(chlProd->units, "mg m^-3", UNITLEN);
        strncpy(chlProd->title, "Chlorophyll Concentration, Default Sensor Algorithm", TITLELEN);
        strncpy(chlProd->standard_name, "chlorophyll_concentration_in_sea_water", TITLELEN);
    }
    
    // allocate lists
    tmpList = (l2prodstr**) malloc((l2prod_num+1) * sizeof (l2prodstr*));
    sortedList = (l2prodstr**) malloc((l2prod_num+1) * sizeof (l2prodstr*));

    // copy list
    for (productIndex = 0; productIndex < l2prod_num; productIndex++) {
        tmpList[productIndex] = l2prod_array[productIndex];
    }

    // add default chl
    tmpList[productIndex] = chlProd;

    // sort list by product name
    for (productIndex = 0; productIndex < l2prod_num+1; productIndex++) {
        product = tmpList[productIndex];
        if (product) {
            getProductName(productName, product);
            sortedList[sortedIndex++] = product; // add to sorted
            tmpList[productIndex] = NULL; // remove from tmp

            // search for matching product entries
            for (productIndex2 = productIndex + 1; productIndex2 < l2prod_num+1; productIndex2++) {
                product2 = tmpList[productIndex2];
                if (product2) {
                    getProductName(productName2, product2);
                    if (strcasecmp(productName, productName2) == 0) {
                        sortedList[sortedIndex++] = product2; // add to sorted
                        tmpList[productIndex2] = NULL; // remove from tmp
                    } // name matches
                } // product2 exists
            } // for product2
        } // product exists
    } // for product

    // open XML file
    fout = fopen(filename, "w");

    // loop sorted list to print XML
    XML_file_header(fout);
    getProductName(productName2, sortedList[0]);
    XML_product_header(fout, sortedList[0]);

    for (productIndex = 0; productIndex < l2prod_num+1; productIndex++) {
        product = sortedList[productIndex];
        getProductName(productName, product);

        // if changed product
        if (strcasecmp(productName, productName2) != 0) {
            strcpy(productName2, productName);
            XML_product_footer(fout);
            XML_product_header(fout, product);
        }
        XML_algorithm(fout, product);
    }

    XML_product_footer(fout);
    XML_file_footer(fout);

    // close XML file
    fclose(fout);

    // free lists
    free(tmpList);
    free(sortedList);
}

